#include "t_box_input.h"

QString T_Box_Input::p_seek_whence_name(int whence)
{
    switch(whence)
    {
    case SEEK_SET: return "SEEK_SET";
    case SEEK_CUR: return "SEEK_CUR";
    case SEEK_END: return "SEEK_END";
    case AVSEEK_SIZE: return "AVSEEK_SIZE";
    default:
        return QString("[%1]").arg(whence);
    }
}

T_Box_Input_File::T_Box_Input_File(QString a_filename)
    : m_file(a_filename)
    , m_buffer(new quint8[c_buffer_size])
{
    if(!m_file.open(QIODevice::ReadOnly))
    {
        qDebug() << "file open failed";
    }
}

T_Box_Input_File::~T_Box_Input_File()
{
    if(m_file.isOpen()) m_file.close();
    delete [] m_buffer;
}

bool T_Box_Input_File::isValid()
{
    if(!m_file.isOpen()) return false;
    return true;
}

AVInputFormat *T_Box_Input_File::getAVInputFormat()
{
    const int c_pd_check_size = 4096;
    quint64 v_pos = m_file.pos();
    QByteArray v_pd_bytes = m_file.read(c_pd_check_size);
    AVProbeData v_probe_data;
    v_probe_data.filename = "";
    v_probe_data.buf_size = v_pd_bytes.size();
    v_probe_data.buf = (unsigned char *)v_pd_bytes.data();
    m_file.seek(v_pos);
    AVInputFormat *v_fmt = av_probe_input_format(&v_probe_data, 1);
    return v_fmt;
}

ByteIOContext *T_Box_Input_File::getByteIOContext()
{
    if(!m_file.isOpen()) return 0;
    int ret = init_put_byte(
            &m_bioc, //ByteIOContext *s
            m_buffer, //unsigned char *buffer,
            c_buffer_size,  //int buffer_size,
            0, //int write_flag,
            this, //void *opaque,
            T_Box_Input_File::callback_read_packet, //int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
            NULL, //int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
            T_Box_Input_File::callback_seek //int64_t (*seek)(void *opaque, int64_t offset, int whence)
            );
    qDebug() << "ret=" << ret;
    return &m_bioc;
}

AVFormatContext	*T_Box_Input_File::getAVFormatContext()
{
    if(!this->isValid())
    {
        qDebug() << "(!this->isValid())";
        return NULL;
    }
    AVInputFormat *v_fmt = this->getAVInputFormat();
    if(!v_fmt)
    {
        qDebug() << "(!v_fmt)";
        return NULL;
    }
    AVFormatContext	*v_format_ctx;
    if(::av_open_input_stream(
            &v_format_ctx,
            this->getByteIOContext(),
            "",
            v_fmt,
            NULL))
    {
        return NULL;
    }
    if(::av_find_stream_info(v_format_ctx)<0)
    {
        qDebug() << "Can't find stream info";
        av_close_input_file(v_format_ctx);
        return NULL;
    }
    return v_format_ctx;
}

T_Box_Player_Context *T_Box_Input_File::getAVFormatContext2()
{
    AVFormatContext	*v_format_ctx = this->getAVFormatContext();
    if(!v_format_ctx) return NULL;
    return new T_Box_Player_Context(v_format_ctx);
}

int T_Box_Input_File::read_packet(uint8_t *buf, int buf_size)
{
    if(!m_file.isOpen()) return 0;
    //qDebug() << "[read_packet()]" << m_file.pos() << buf_size;
    return m_file.read((char *)buf, buf_size);
}

int64_t T_Box_Input_File::seek(int64_t offset, int whence)
{
    if(!m_file.isOpen()) return -1;
    QString v_whence_name = p_seek_whence_name(whence);
    if(whence == SEEK_CUR)
    {
        qDebug() << "[seek()]" <<v_whence_name << offset << m_file.pos();
    }
    else
    {
        qDebug() << "[seek()]" <<v_whence_name << offset;
    }
    switch(whence)
    {
    case SEEK_SET:
        break;
    case SEEK_CUR:
        offset += m_file.pos();
        break;
    case SEEK_END:
        offset += m_file.size();
        break;
    case AVSEEK_SIZE:
        // return the filesize without seeking anywhere
        return m_file.size();
    default:
        return -1;
    }
    if(!m_file.seek(offset))
    {
        return -1;
    }
    else
    {
        return m_file.pos();
    }
}

